#!/usr/bin/perl -w
use strict;

# Problematic tags
# GTPase, gtpase, 2H, 2h, TAP, tap, chip, CD, cd
# tem: case sensitive
# SEM

# Format the results as per BioCreative 3 instructions
# 1. Article Identifier
# 2. Interaction detection method (MI Identifier)
# 4. Unique rank in the range 1..n where n is the total number of hits for the article
# 5. Confidence
# 6. Evidence sentence

my $abstract_tag_file = $ARGV[0];
my $method_tag_file = $ARGV[1];
my $article_tag_file = $ARGV[2];

my %abstract_count;
my %abstract_termid_count;
my %abstract_termid_term;
my %abstract_termid_context;
# print "Reading $abstract_tag_file\n";
&read_tags ($abstract_tag_file, 0);

my %method_count;
my %method_termid_count;
my %method_termid_term;
my %method_termid_context;
my %abstract_method_count;
my %abstract_method_term;
# print "Reading $method_tag_file\n";
&read_tags ($method_tag_file, 1);

my %article_count;
my %article_termid_count;
my %article_termid_term;
my %article_termid_context;
my %abstract_method_article_count;
my %abstract_method_article_term;
&read_tags ($article_tag_file, 2);

&consolidate_tags;
# &print_tags;
# &print_statistics;

sub print_statistics{ 
	# Print no. of common terms
	foreach my $key (keys(%abstract_method_article_count)){ 
		print $key . " " . 
			$abstract_method_article_count{$key} . "/" . 
			$article_count{$key} . " "; 	

		if (exists($method_count{$key})){ 
			print $abstract_method_article_count{$key} . "/" .
				$method_count{$key} . " ";
		} else { 
			print "NO ";
		}

		if (exists($abstract_count{$key})){ 
			print $abstract_method_article_count{$key} . "/" .
				$abstract_count{$key} . " ";
		} else { 
			print "NO";
		}
		print "\n";
	}

	foreach my $key (keys(%article_count)){ 
		next if (exists($abstract_method_article_count{$key}));
		print $key . " ";
		print $article_count{$key} . " ";
		
		if (exists($method_count{$key})){ 
				print $method_count{$key} . " ";
		} else { 
				print "NO ";
		}

		if (exists($abstract_count{$key})){ 
			print $abstract_count{$key} . " ";
		} else { 
			print "NO";
		}
		print "\n";
	}

	foreach my $key (keys(%method_count)){ 
		next if (exists($abstract_method_article_count{$key}));
		next if (exists($article_count{$key}));
		
		print $key . " ";
		
		if (exists($article_count{$key})){ 
				print $article_count{$key} . " ";
		} else { 
				print "NO ";
		}
	
		print $method_count{$key} . " ";

		if (exists($abstract_count{$key})){ 
			print $abstract_count{$key} . " ";
		} else { 
			print "NO";
		}
		print "\n";
	}
	
	foreach my $key (keys(%abstract_count)){ 
		next if (exists($abstract_method_article_count{$key}));
		next if (exists($article_count{$key}));
		next if (exists($method_count{$key}));
		
		print $key . " ";
		
		if (exists($article_count{$key})){ 
				print $article_count{$key} . " ";
		} else { 
				print "NO ";
		}
	
		if (exists($method_count{$key})){ 
				print $method_count{$key} . " ";
		} else { 
				print "NO ";
		}

		print $abstract_count{$key} . " ";
		print "\n";
	}
}

sub consolidate_tags{ 
	my %combined_tags;
	foreach my $key (keys(%abstract_termid_count)){ 
		my ($pmid, $id) = split (/\-/, $key);
		if (not exists($combined_tags{$pmid})){	
			$combined_tags{$pmid} = $id;
		} else { 
			next if ($combined_tags{$pmid} =~ /$id/);
			$combined_tags{$pmid} .= "," . $id;
		}
	}

	foreach my $key (keys(%method_termid_count)){ 
		my ($pmid, $id) = split (/\-/, $key);
		if (not exists($combined_tags{$pmid})){	
			$combined_tags{$pmid} = $id;
		} else { 
			next if ($combined_tags{$pmid} =~ /$id/);
			$combined_tags{$pmid} .= "," . $id;
		}
	}

	foreach my $key (keys(%article_termid_count)){ 
		my ($pmid, $id) = split (/\-/, $key);
		if (not exists($combined_tags{$pmid})){	
			$combined_tags{$pmid} = $id;
		} else { 
			next if ($combined_tags{$pmid} =~ /$id/);
			$combined_tags{$pmid} .= "," . $id;
		}
	}

	foreach my $key (keys(%combined_tags)){ 
		my @tids = split (/\,/, $combined_tags{$key});
		
		my %retained;
	 	for (my $k = 0; $k < scalar(@tids); $k++){ 
			$retained{$tids[$k]} = 1;
		}	

	 	for (my $k = 0; $k < scalar(@tids); $k++){ 
			next if ($retained{$tids[$k]} == 0);
			my $combined_terms_k = &get_combined_terms ($key, $tids[$k]);
			# print "Combined terms for $tids[$k] " . $combined_terms_k . "\n";
			for (my $j = $k + 1; $j < scalar(@tids); $j++){ 
				my $combined_terms_j = &get_combined_terms ($key, $tids[$j]);
				# print "Combined terms for $tids[$j] " . $combined_terms_j . "\n";
				my $remove_id = &get_duplicate ($combined_terms_k, $combined_terms_j);	
				# print "Comparison: " . $remove_id . "\n";
				next if ($remove_id == -1);
				if ($remove_id == 1){ 
					#print "Removing " . $tids[$k] . " with " . 
					# $combined_terms_k . " for " .  $tids[$j] . " with " .
					# $combined_terms_j , "\n"; 
					 $retained{$tids[$k]} = 0;
				} elsif ($remove_id == 2){ 
					#print "Removing " . $tids[$j] . " with " . 
					#$combined_terms_j . " for " .  $tids[$k] . " with " .
					#$combined_terms_k , "\n"; 
					$retained{$tids[$j]} = 0;
				}
			}	
		}	

		my %rank_evd;
		foreach my $term_key (keys(%retained)){ 

			# Problematic tags
			# GTPase, gtpase, 2H, 2h, TAP, tap, chip, CD, cd
			# tem, fluorescence, SEM
			my $term_text = &get_combined_terms ($key, $term_key);
			if ($term_text eq "GTPase" or $term_text eq "gtpase" 
				or $term_text eq "2H" or $term_text eq "2h" 
				or $term_text eq "TAP" or $term_text eq "tap" 
				or $term_text eq "chip" or $term_text eq "CD"
				or $term_text eq "cd" or $term_text eq "Cd" 
				or $term_text eq "tem" or $term_text eq "SEM"  
				or $term_text eq "fluorescence"){ 
				# print "REMOVING " . $key . " " . $term_key . " " . 
				#$ term_text . " " .
				#&get_combined_evidence ($key, $term_key) . " " .
				#"\n"; 
				next;
			}
		
			my $cevd = &get_combined_evidence ($key, $term_key);
			$cevd =~ s/\#/HASH/g;
			my @sents = split (/\|/, $cevd);
			my $evd_sent = $key . "\t" . $term_key . "\t" . 
				$term_text . "\t" . $cevd ; 
			if (not exists($rank_evd{scalar(@sents)})){ 
				$rank_evd{scalar(@sents)} = $evd_sent; 
			} else { 
				$rank_evd{scalar(@sents)} .= "#" . $evd_sent;
			}
		}	

		my $rank_idx = 1;
		foreach my $rank_key(sort{$b <=> $a}keys(%rank_evd)){ 
			my @sents = split (/\#/, $rank_evd{$rank_key});
			for (my $k = 0; $k < scalar(@sents); $k++){ 
				# print $sents[$k] . "\n";
				my @fs = split (/\t/, $sents[$k]);
				if (scalar(@fs) < 4){ 
					print "Existing " . $sents[$k] . "\n";
					exit;
				}
			
				$fs[3] =~ s/HASH/\#/g;
				print $fs[0] . "\t" . $fs[1] . "\t" . 
					$rank_idx . "\t" . "1" . "\t" . $fs[3] . 
					"\n";  
				$rank_idx++;
			} 
		}
	}	
}

sub get_duplicate{ 
	my ($terms_k, $terms_j) = @_;
	# print "Checking " . $terms_k . " and " . $terms_j . "\n";
	if (not ($terms_k =~ /\|/) and not ($terms_j =~ /\|/)){ 
		if ($terms_k eq $terms_j){ 
			return 2; # remove terms_j
		} else { 
			return -1;
		}
	}

	my @ttj = split (/\|/, $terms_j);
	my $count = 0;
	for (my $j = 0; $j < scalar(@ttj); $j++){ 
		next if (not $terms_k =~ /$ttj[$j]/);
		$count++;
	}
	
	if ($count == scalar(@ttj)){ return 2; }
	
	my @ttk = split (/\|/, $terms_k);
	$count = 0;
	for (my $j = 0; $j < scalar(@ttk); $j++){ 
		next if (not $terms_j =~ /$ttk[$j]/);
		$count++;
	}

	if ($count == scalar(@ttk)){ return 1; }
	return -1;
}

sub get_combined_terms{ 
	my ($pmid, $tid) = @_;
	
	my $cterms = "";
	my $key = $pmid . "-" . $tid;
	if (exists($abstract_termid_term{$key})){ 
		$cterms = &get_uniq_terms($cterms, $abstract_termid_term{$key});
	} 
	if (exists($method_termid_term{$key})){ 
		$cterms = &get_uniq_terms($cterms, $method_termid_term{$key});
	} 
	if (exists($article_termid_term{$key})){ 
		$cterms = &get_uniq_terms($cterms, $article_termid_term{$key});
	} 

	return $cterms;
}

sub get_combined_evidence{ 
	my ($pmid, $tid) = @_;
	
	my $cterms = "";
	my $key = $pmid . "-" . $tid;
	if (exists($abstract_termid_context{$key})){ 
		$cterms = &get_uniq_sent($cterms, $abstract_termid_context{$key});
	} 

	if (exists($method_termid_term{$key})){ 
		$cterms = &get_uniq_sent($cterms, $method_termid_context{$key});
	} 

	if (exists($article_termid_term{$key})){ 
		$cterms = &get_uniq_sent($cterms, $article_termid_context{$key});
	} 
	
	$cterms =~ s/^\|//;
	return $cterms;
}

sub get_uniq_sent{ 
	my ($cterm, $new_terms) = @_;
	
	$new_terms =~ s/[1-9][0-9]*\#//g;

	my @old = split (/\|/, $cterm);
	my @new = split (/\|/, $new_terms);
	
	for (my $i = 0; $i < scalar(@new); $i++){
		my $flag = 1;	
		for (my $k = 0; $k < scalar(@old); $k++){
			next if ($new[$i] ne $old[$k]);
			$flag = 0;
		}

		if ($flag == 1){ 
			if ($cterm eq ""){ 
				$cterm = $new[$i];
			} else{ 
				$cterm .= "|" . $new[$i];
			} 
		}
	}
	return $cterm;
}


sub get_uniq_terms{ 
	my ($cterm, $new_terms) = @_;
	# print $new_terms . "\n";
	my @tfs = split (/\|/, $new_terms);
	for (my $k = 0; $k < scalar(@tfs); $k++){ 
		if ($cterm eq ""){ 
			$cterm = $tfs[$k];
		} else { 
			next if ($cterm =~ /$tfs[$k]/);
			$cterm .= "|" . $tfs[$k];
		}
	}	
	return $cterm;
}

sub print_tags{ 
	foreach my $key (keys(%abstract_termid_count)){ 
		print $key . "#" . $abstract_termid_term{$key} . 
			"#ABSTRACT\n";
	}

	foreach my $key (keys(%method_termid_count)){ 
		print $key . "#" . $method_termid_term{$key} . 
			"#METHOD\n";
		# print $method_termid_context{$key} . "\n"; 
	}

	foreach my $key (keys(%article_termid_count)){ 
		print $key . "#" . $article_termid_term{$key} . 
			"#ARTICLE\n";
		# print $article_termid_context{$key} . "\n";
	}
}

#print "PMID ALL ABSTRACT-METHOD\n";
#foreach my $key (keys(%aam_count)){ 
#	print $key . " " . $aam_count{$key} . " " . 
#		$abstract_method_count{$key} . "\n";	
#}
#exit;
#
#foreach my $key (keys(%abstract_termid_count)){ 
#	next if (exists($abstract_method_present{$key}));
#	my $term = $abstract_termid_term{$key};
#	my $context = $abstract_termid_context{$key};
#	$key =~ s/\-/\ /;
#	print $key . " " . $term . " ABSTRACT ";
#	print $context;
#	print "\n";
#}

sub read_tags{
	my ($prediction_file, $type) = @_;

	open (FD, $prediction_file)
		|| die ("Unable to open: $prediction_file\n");
	while (<FD>){ 
		chop;
		next if ($_ eq "");		

		# 0: PMID
		# 1: SentNo
		# 2: Context
		# 3: Term
		# 4: ID
		# 5: Type
		# 6: No of occurrences
		# 7: Start
		# 8: End
		# 9: Occurrence Position
		# 10: Length
		# 11: Confidence
		my @tfs = split (/\t/, $_);
		next if (scalar(@tfs) < 11);			
		
		$tfs[3] =~ s/\\//g;
		if ($type == 0){ 
			update_abstract ($tfs[0], $tfs[1], $tfs[2], $tfs[3], $tfs[4]);
		} elsif ($type == 1){
			update_method ($tfs[0], $tfs[1], $tfs[2], $tfs[3], $tfs[4]);
		} elsif ($type == 2){ 
			update_article ($tfs[0], $tfs[1], $tfs[2], $tfs[3], $tfs[4]);
		}
	}
	close (FD);
}

sub update_abstract{
	my ($pmid, $sentno, $context, $term, $termid) = @_;	

	my $key = $pmid . "-" . $termid;
	if (not exists ($abstract_termid_count{$key})){ 
		$abstract_termid_count{$key} = 1;
		$abstract_termid_term{$key} = $term;
		$abstract_termid_context{$key} = $sentno . "#" . $context;

		# Update PMID wise count;
		if (not exists ($abstract_count{$pmid})){ 
			$abstract_count{$pmid} = 1;
		} else { 
			$abstract_count{$pmid} += 1;
		}
	} else { 
		$abstract_termid_count{$key} += 1;
		$abstract_termid_context{$key} .= "|" . $sentno . "#" . $context;
		return if ($abstract_termid_term{$key} =~ /$term/);
		$abstract_termid_term{$key} .= "|" . $term;
	}
}

sub update_method{
	my ($pmid, $sentno, $context, $term, $termid) = @_;	

	my $key = $pmid . "-" . $termid;
	if (not exists ($method_termid_count{$key})){ 
		$method_termid_count{$key} = 1;
		$method_termid_term{$key} = $term;
		$method_termid_context{$key} = $sentno . "#" . $context;

		# Update PMID wise count;
		if (not exists ($method_count{$pmid})){ 
			$method_count{$pmid} = 1;
		} else { 
			$method_count{$pmid} += 1;
		}

		# Update abstract + method
		if (exists ($abstract_termid_count{$key})){
			$abstract_method_term{$key} = 1;
			if (exists($abstract_method_count{$pmid})){
				$abstract_method_count{$pmid} = 1;
			} else { 
				$abstract_method_count{$pmid} += 1;
			}
		} 
	} else { 
		$method_termid_count{$key} += 1;
		$method_termid_context{$key} .= "|" . $sentno . "#" . $context;
		return if ($method_termid_term{$key} =~ /($term)/);
		$method_termid_term{$key} .= "|" . $term;
	}
}

sub update_article{
	my ($pmid, $sentno, $context, $term, $termid) = @_;	

	my $key = $pmid . "-" . $termid;
	if (not exists ($article_termid_count{$key})){ 
		$article_termid_count{$key} = 1;
		$article_termid_term{$key} = $term;
		$article_termid_context{$key} = $sentno . "#" . $context;

		# Update PMID wise count;
		if (not exists ($article_count{$pmid})){ 
			$article_count{$pmid} = 1;
		} else { 
			$article_count{$pmid} += 1;
		}
		
		# Update abstract + method
		if (exists ($abstract_termid_count{$key}) and 
			exists ($method_termid_count{$key})){
			$abstract_method_article_term{$key} = 1;
			
			if (exists($abstract_method_article_count{$pmid})){
				$abstract_method_article_count{$pmid} = 1;
			} else { 
				$abstract_method_article_count{$pmid} += 1;
			}
		} 
	} else { 
		$article_termid_count{$key} += 1;
		$article_termid_context{$key} .= "|" . $sentno . "#" . $context;
		return if ($article_termid_term{$key} =~ /($term)/);
		$article_termid_term{$key} .= "|" . $term;
	}
}
